﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using Medianamik.Core;

namespace Medianamik.UI.Controls
{
    public delegate void NavigateParentEventHandler(object sender,
        NavigateParentEventArgs e);

    [ToolboxData("<{0}:BreadcrumbTrail runat=\"server\"> </{0}:BreadcrumbTrail>")]
    public class BreadcrumbTrail : CompositeControl
    {
        #region Fields

        readonly Repeater _repeater = new Repeater();
        const string PostBackEventTarget = "__EVENTTARGET";
        const string PostBackEventArgument = "__EVENTARGUMENT";

        #endregion

        #region Properties

        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }

        public IEnumerable<Breadcrumb> Breadcrumbs { get; set; }

        public string Url
        {
            get
            {
                object o = ViewState["Url"];
                return ((o == null) ? string.Empty : (string)o);
            }
            set
            {
                ViewState["Url"] = value;
            }
        }

        public string ParamName
        {
            get
            {
                object o = ViewState["ParamName"];
                return ((o == null) ? string.Empty : (string)o);
            }
            set
            {
                ViewState["ParamName"] = value;
            }
        }

        public string PostBackClientEvent
        {
            get
            {
                object o = ViewState["PostBackClientEvent"];
                return ((o == null) ? string.Empty : (string)o);
            }
            set
            {
                ViewState["PostBackClientEvent"] = value;
            }
        }

        public bool HideLonelyBreadcrumb
        {
            get
            {
                return ViewState["HideLonelyBreadcrumb"] as bool? ?? false;
            }
            set { ViewState["HideLonelyBreadcrumb"] = value; }
        }

        public string ItemCssClass
        {
            get
            {
                object o = ViewState["ItemCssClass"];
                return ((o == null) ? string.Empty : (string)o);
            }
            set
            {
                ViewState["ItemCssClass"] = value;
            }
        }

        #endregion

        #region Events

        #region OnNavigate Event

        public event NavigateParentEventHandler NavigateParent;
        protected virtual void OnNavigateParent(NavigateParentEventArgs e)
        {
            if (NavigateParent != null)
                NavigateParent(this, e);
        }

        #endregion

        #endregion

        #region Methods

        protected override void CreateChildControls()
        {
            Controls.Add(_repeater);

            _repeater.HeaderTemplate = new BreadcrumbTrailHeaderTemplate(CssClass);
            _repeater.ItemTemplate = new BreadcrumbTrailItemTemplate(Url, ParamName,
                Parent.ClientID + "_" + ControlIDs.BreadcrumbTrail, ItemCssClass);
            _repeater.FooterTemplate = new BreadcrumbTrailFooterTemplate();
        }

        public override void DataBind()
        {
            base.DataBind();

            if (Breadcrumbs != null)
            {
                if (HideLonelyBreadcrumb && Breadcrumbs.Count() <= 1)
                    _repeater.DataSource = new List<Breadcrumb>();
                else
                    _repeater.DataSource = Breadcrumbs;
            }

            _repeater.DataBind();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!String.IsNullOrEmpty(Page.Request[PostBackEventTarget])
                && Page.Request[PostBackEventTarget].Contains(ControlIDs.BreadcrumbTrail)
                && !String.IsNullOrEmpty(Page.Request[PostBackEventArgument]))
            {
                OnNavigateParent(new NavigateParentEventArgs(Page.Request[PostBackEventArgument]));
            }
        }

        #endregion

        #region Inner Classes

        class BreadcrumbTrailHeaderTemplate : ITemplate
        {
            readonly string _cssClass;
            Literal _literal;

            public BreadcrumbTrailHeaderTemplate(string cssClass)
            {
                _cssClass = cssClass;
            }

            public void InstantiateIn(Control container)
            {
                _literal = new Literal();
                container.Controls.Add(_literal);
                _literal.DataBinding += _literal_DataBinding;

            }

            void _literal_DataBinding(object sender, EventArgs e)
            {
                var container = (RepeaterItem)_literal.NamingContainer;
                var breadcrumbTrail = (BreadcrumbTrail)container.NamingContainer.NamingContainer;
                int count = breadcrumbTrail.Breadcrumbs.Count();

                if (count > 1 || (breadcrumbTrail.HideLonelyBreadcrumb == false && count > 0))
                {
                    string css = "";

                    if (!String.IsNullOrEmpty(_cssClass))
                        css = string.Format(" class=\"{0}\"", _cssClass);

                    _literal.Text = String.Format("<ul id=\"FilAriane\"{0}>", css);
                }
                else
                {
                    _literal.Text = "";
                }
            }
        }

        class BreadcrumbTrailItemTemplate : ITemplate
        {
            readonly string _url;
            readonly string _paramName;
            Literal _breadcrumb;
            readonly string _controID;
            private readonly string _itemCssClass;

            public BreadcrumbTrailItemTemplate(string url, string paramName,
                string controID, string itemCssClass)
            {
                _url = url;
                _paramName = paramName;
                _controID = controID;
                _itemCssClass = itemCssClass;
            }

            void Breadcrumb_DataBinding(object sender, EventArgs e)
            {
                var container = (RepeaterItem)_breadcrumb.NamingContainer;
                var breadcrumb = (Breadcrumb)container.DataItem;
                var breadcrumbTrail = (BreadcrumbTrail)container.NamingContainer.NamingContainer;

                if (container.ItemIndex == (breadcrumbTrail.Breadcrumbs.Count() - 1))
                {
                    _breadcrumb.Text = String.Format("<li class=\"DernierItem{0}\">{1}</li>",
                        String.IsNullOrEmpty(_itemCssClass) ? "" : " " + _itemCssClass, breadcrumb.Name);
                }
                else if (String.IsNullOrEmpty(_url) || String.IsNullOrEmpty(_paramName)) //Postback
                {
                    string id = _controID + "_" + container.ItemIndex;

                    _breadcrumb.Text = String.Format("<li><a id=\"{0}\" href=\"javascript:{1}('{0}','{2}')\"{5} name=\"{3}\">{4}</a></li>",
                        id, breadcrumbTrail.PostBackClientEvent.Equals(String.Empty) ? "__doPostBack" : breadcrumbTrail.PostBackClientEvent,
                            breadcrumb.ID ?? "", id.Replace('_', '$'), breadcrumb.Name, String.IsNullOrEmpty(_itemCssClass) ? "" : " class=\"" + _itemCssClass + "\"");

                }
                else
                {
                    _breadcrumb.Text = String.Format("<li><a{3} href=\"{0}{1}\">{2}</a></li>",
                        _url, String.IsNullOrEmpty(breadcrumb.ID) ? "" : String.Format("?{0}={1}", _paramName, breadcrumb.ID),
                        breadcrumb.Name, String.IsNullOrEmpty(_itemCssClass) ? "" : " class=\"" + _itemCssClass + "\"");
                }
            }

            public void InstantiateIn(Control container)
            {
                _breadcrumb = new Literal();
                container.Controls.Add(_breadcrumb);
                _breadcrumb.DataBinding += Breadcrumb_DataBinding;
            }
        }

        class BreadcrumbTrailFooterTemplate : ITemplate
        {
            Literal _literal;

            public void InstantiateIn(Control container)
            {
                _literal = new Literal();
                container.Controls.Add(_literal);
                _literal.DataBinding += _literal_DataBinding;
            }

            void _literal_DataBinding(object sender, EventArgs e)
            {
                var container = (RepeaterItem)_literal.NamingContainer;
                var breadcrumbTrail = (BreadcrumbTrail)container.NamingContainer.NamingContainer;
                int count = breadcrumbTrail.Breadcrumbs.Count();

                if (count > 1 || (breadcrumbTrail.HideLonelyBreadcrumb == false && count > 0))
                {
                    _literal.Text = "</ul><div class=\"clearer\"></div>";
                }
                else
                {
                    _literal.Text = "";
                }
            }
        }

        #endregion
    }

    public class NavigateParentEventArgs : EventArgs
    {
        public NavigateParentEventArgs(string itemID)
        {
            ItemID = itemID;
        }

        public string ItemID { get; private set; }
    }
}
